1
1
.
.
1
1
1
1
.
.
6
6
S
S
t
t
e
e
p
p
6
6
-
-
A
A
u
u
t
t
h
h
e
e
n
n
t
t
i
i
c
c
a
a
t
t
e
e
I
I
n
n
f
f
o
o
[
[
G
G
]
]
Up until this point we have been using /CreateJWT to return JWT with hard coded data and without any Authentication.
In other words we didn't provide any Credentials and we didn't compare them with stored Credentials to identify User.
So in this last step we will add this missing part and we will return JWT only if User is Authenticated.
For this purpose we will create new /Authenticate Endpoint that will compare provided Credentials with stored ones.
Application Schema [Results]
MyAuthentication
Manager
http://localhost:8080/GetJWT?enteredUsername=myuser&enteredPassword=mypassword
Tomcat
getJWT()
Postman
JWTController
hello()
WebSecurityConfig
P
P
r
r
o
o
c
c
e
e
d
d
u
u
r
r
e
e
Inside Package: config
– Create Class: MyAuthenticationManager.java (Compare entered Credentials with stored ones)
Edit Class: JWTController.java (Add anonymous Endpoint "/Authenticate")
Edit Class: WebSecurityConfig.java (Allow access to anonymous Endpoint "/Authenticate")
MyAuthenticationManager.java
package com.ivoronline.springboot_security_jwt.config;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class MyAuthenticationManager implements AuthenticationManager {
@Override
public Authentication authenticate(Authentication enteredAuthentication) {
//GET ENTERED CREDENTIALS
String enteredUsername = (String) enteredAuthentication.getPrincipal(); //ENTERED USERNAME
String enteredPassword = (String) enteredAuthentication.getCredentials(); //ENTERED PASSWORD
//GET STORED CREDENTIALS
//Here they are hard coded (for simplicity reason)
//Call UserDetailsService(enteredUsername) to get UserDetails with Password & Authorities from DB
String storedUsername = "admin";
String storedPassword = "adminpassword";
String storedAuthorities = "book.create, book.delete";
//AUTHENTICATE USER (COMPARE ENTERED AND STORED CREDENTIALS)
if (!enteredUsername.equals(storedUsername)) { System.out.println("Username not found"); return null; }
if (!enteredPassword.equals(storedPassword)) { System.out.println("Incorrect Password"); return null; }
//CREATE AUTHORITIES
String[] authoritiesArray = storedAuthorities.split(", ");
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for(String authority : authoritiesArray) {
authorities.add(new SimpleGrantedAuthority(authority));
}
//CREATE VALIDATED AUTHENTICATION
Authentication validatedAuth = new UsernamePasswordAuthenticationToken(enteredUsername, null,
authorities);
//RETURN VALIDATES AUTHENTICATION
return validatedAuth;
}
}
JWTController.java
package com.ivoronline.springboot_security_jwt.controllers;
import com.ivoronline.springboot_security_jwt.config.JWTUtil;
import com.ivoronline.springboot_security_jwt.config.MyAuthenticationManager;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class JWTController {
@Autowired JWTUtil jwtUtil;
@Autowired MyAuthenticationManager myAuthenticationManager;
//==================================================================
// GET JWT
//==================================================================
@ResponseBody
@RequestMapping("/GetJWT")
public String getJWT(@RequestParam String enteredUsername, @RequestParam String enteredPassword) {
//AUTHENTICATE (COMPARE ENTERED AND STORED CREDENTIALS)
Authentication enteredAuth = new UsernamePasswordAuthenticationToken(enteredUsername, enteredPassword);
Authentication returnedAuth = myAuthenticationManager.authenticate(enteredAuth);
//CHECK AUTHENTICATION
if(returnedAuth == null) { return "User is NOT Authenticated"; }
//CREATE JWT
String username = (String) returnedAuth.getPrincipal();
String role = (String) returnedAuth.getAuthorities().toString().replace("[","").replace("]","");
String jwt = jwtUtil.createJWT(username, role);
//RETURN JWT
return jwt;
}
//=============================================================
// CREATE JWT
//=============================================================
@ResponseBody
@RequestMapping("/CreateJWT")
public String createJWT() {
//CREATE JWT
String jwt = jwtUtil.createJWT("admin", "[book.create, book.delete]");
//RETURN JWT
return jwt;
}
//=============================================================
// GET CLAIMS
//=============================================================
@ResponseBody
@RequestMapping("/GetClaims")
public Claims getClaims(@RequestHeader("Authorization") String authorization) {
//EXTRACT JWT FROM AUTHORIZATION HEADER
String jwt = jwtUtil.extractJWTFromAuthorizationHeader(authorization);
//GET CLAIMS
Claims claims = jwtUtil.getClaims(jwt);
//RETURN CLAIMS
return claims;
}
//=============================================================
// GET USERNAME
//=============================================================
@ResponseBody
@RequestMapping("/GetUsername")
public String getUsername(@RequestHeader("Authorization") String authorization) {
//EXTRACT JWT FROM AUTHORIZATION HEADER
String jwt = jwtUtil.extractJWTFromAuthorizationHeader(authorization);
//GET USERNAME
String username = jwtUtil.getUsername(jwt);
//RETURN USERNAME
return username;
}
}
WebSecurityConfig.java
package com.ivoronline.springboot_security_jwt.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired private MyFilter myFilter;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
//ANONYMOUS ACCESS
httpSecurity.authorizeRequests().antMatchers("/GetJWT" ).permitAll(); //To get Authenticated JWT
httpSecurity.authorizeRequests().antMatchers("/CreateJWT" ).permitAll(); //To get hard coded JWT
httpSecurity.authorizeRequests().antMatchers("/GetClaims" ).permitAll(); //For Testing
httpSecurity.authorizeRequests().antMatchers("/GetUsername" ).permitAll(); //For Testing
//OTHER CONFIGURATION
httpSecurity.csrf().disable(); //Enables POST
httpSecurity.authorizeRequests().anyRequest().authenticated(); //Authenticated
httpSecurity.addFilterBefore(myFilter, UsernamePasswordAuthenticationFilter.class); //Add Filter
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); //No Session
}
}
R
R
e
e
s
s
u
u
l
l
t
t
s
s
http://localhost:8080/GetJWT?enteredUsername=admin&enteredPassword=adminpassword
P
P
o
o
s
s
t
t
m
m
a
a
n
n
GET
http://localhost:8080/CreateBook
Headers (add Key-Value)
Authorization: Bearer
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJUZXN0SldUIiwicm9sZSI6IlJPTEVfVVNFUiIsImlzcyI6Iml2b3JvbmxpbmUiLCJqdGkiOiIxIiwi
dXNlcm5hbWUiOiJteXVzZXIifQ.g7CcreAHQvSR1JjQJqTBvT3eGcpz9kcuVOkgUFREiIc
Postman